#include "DocumentObjectFactory.h"

#include "PadStack.h"
#include "PadStackElement.h"
#include "PadStackInstance.h"
#include "LandPattern.h"
#include "Terminal.h"
#include "Arrangements/QuadInLineArrangement.h"

#include "Primitives/ArcOfCircle.h"
#include "Primitives/ButterflyPrimitive.h"
#include "Primitives/CirclePrimitive.h"
#include "Primitives/RectanglePrimitive.h"
#include "Primitives/TrianglePrimitive.h"
#include "Primitives/RegularPolygonPrimitive.h"

DocumentObjectFactory::DocumentObjectFactory(QObject *parent)
    : IDocumentObjectFactory(parent)
{
    registerMetaClass<PadStack>();
    registerMetaClass<PadStackElement>();
    registerMetaClass<PadStackInstance>();
    registerMetaClass<LandPattern>();
    registerMetaClass<Terminal>();
    registerMetaClass<QuadInLineArrangement>();
    registerMetaClass<Primitive>();
    registerMetaClass<CirclePrimitive>();
    registerMetaClass<RectanglePrimitive>();
    registerMetaClass<TrianglePrimitive>();
    registerMetaClass<ButterflyPrimitive>();
    registerMetaClass<RegularPolygonPrimitive>();
    registerMetaClass<ArcOfCircle>();

    registerMetaEnum<L7::PadStackRole>(
                MetaEnum({
                             {L7::UnkownPadStackRole, {
                                  "Unknown",
                                  "padstack-role-unknown"}},
                             {L7::SurfaceTerminal, {
                                  "Surface terminal",
                                  "padstack-role-surface-terminal"}},
                             {L7::ThroughTerminal, {
                                  "Through terminal",
                                  "padstack-role-through-terminal"}},
                             {L7::Via, {
                                  "Via",
                                  "padstack-role-via2"}},
                             {L7::TestPoint, {
                                  "Test point",
                                  "padstack-role-testpoint"}},
                             {L7::Fiducial, {
                                  "Fiducial",
                                  "padstack-role-fiducial"}},
                             {L7::Mechanical, {
                                  "Mechanical",
                                  "padstack-role-mechanical2"}},
                         }));
    registerMetaEnum<L7::PadStackElementFunction>(
                MetaEnum({
                             {L7::UnknownElementFunction, {
                                  "Unknown",
                                  "padstackelement-function-unknown"}},
                             {L7::MountedLand, {
                                  "Mounted land",
                                  "padstackelement-function-mountedland"}},
                             {L7::OppositeLand, {
                                  "Opposite land",
                                  "padstackelement-function-oppositesland"}},
                             {L7::MountedSolderMask, {
                                  "Mounted solder mask",
                                  "padstackelement-function-mountedsoldermask"}},
                             {L7::OppositeSolderMask, {
                                  "Opposit solder mask",
                                  "padstackelement-function-oppositesoldermask"}},
                             {L7::MountedSolderPaste, {
                                  "Mounted solder paste",
                                  "padstackelement-function-mountedsolderpaste"}},
                             {L7::OppositeSolderPaste, {
                                  "Opposite solder paste",
                                  "padstackelement-function-oppositesolderpaste"}},
                             {L7::MountedAssembly, {
                                  "Mounted assembly",
                                  "padstackelement-function-mountedassembly"}},
                             {L7::OppositeAssembly, {
                                  "Opposite assembly",
                                  "padstackelement-function-oppositeassembly"}},
                             {L7::InternalLand, {
                                  "Internal land",
                                  "padstackelement-function-internal"}},
                             {L7::PlaneLand, {
                                  "Plane land",
                                  "padstackelement-function-plane"}},
                             {L7::ThermalReliefLand, {
                                  "Thermal relief land",
                                  "padstackelement-function-thermalrelief"}},
                             {L7::Hole, {
                                  "Hole",
                                  "padstackelement-function-hole"}},
                             {L7::KeepOut, {
                                  "Keepout",
                                  "padstackelement-function-keepout"}},
                         }));

    registerMetaFlag<L7::CornerLocations>(
                MetaEnum({
                             {L7::TopLeftCorner, {
                                  "Top-left",
                                  "cornerlocation-topleft"}},
                             {L7::BottomLeftCorner, {
                                  "Bottom-left",
                                  "cornerlocation-bottomleft"}},
                             {L7::TopRightCorner, {
                                  "Top-right",
                                  "cornerlocation-topright"}},
                             {L7::BottomRightCorner, {
                                  "Bottom-right",
                                  "cornerlocation-bottomright"}},
                         }));
    registerMetaFlag<ButterflyPrimitive::Shape>(
                MetaEnum({
                             {ButterflyPrimitive::Round, {
                                  "Round",
                                  "primitive-special-butterfly-round"}},
                             {ButterflyPrimitive::Square, {
                                  "Square",
                                  "primitive-special-butterfly-round"}},
                         }));
}

QList<int> DocumentObjectFactory::objectTypeIds() const
{
    return m_creators.keys();
}

LDO::IDocumentObject *DocumentObjectFactory::createObject(int typeId) const
{
    if (!m_creators.contains(typeId))
        return nullptr;
    return m_creators.value(typeId)();
}

QString DocumentObjectFactory::typeName(int typeId) const
{
    const QString name(QMetaType::typeName(typeId));
    return name.left(name.count() - 1);
}

QString DocumentObjectFactory::iconName(int typeId, const LDO::IDocumentObject *object) const
{
    Q_UNUSED(typeId);

    if (qobject_cast<const PadStack*>(object) != nullptr)
    {
        const int enumId = QMetaType::type("L7::PadStackRole");
        const L7::PadStackRole role = qobject_cast<const PadStack*>(object)->role();
        return m_enums.value(enumId).valueMap.value(int(role)).iconName;
    }
    else if (qobject_cast<const PadStackElement*>(object) != nullptr)
    {
        const int enumId = QMetaType::type("L7::PadStackElementFunction");
        const L7::PadStackElementFunction function = qobject_cast<const PadStackElement*>(object)->function();
        return m_enums.value(enumId).valueMap.value(int(function)).iconName;
    }
    return QString();
}
